﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ThoughtWorks.QRCode.Codec;

namespace Comon {
	public class QrCodeHelper {
		/// <summary>
		/// 生成二维码
		/// </summary>
		/// <param name="Content">内容文本</param>
		/// <param name="QRCodeEncodeMode">二维码编码方式</param>
		/// <param name="QRCodeErrorCorrect">纠错码等级</param>
		/// <param name="QRCodeVersion">二维码版本号 0-40</param>
		/// <param name="QRCodeScale">每个小方格的预设宽度（像素），正整数</param>
		/// <param name="size">图片尺寸（像素），0表示不设置</param>
		/// <param name="border">图片白边（像素），当size大于0时有效</param>
		/// <returns></returns>

		public System.Drawing.Image CreateQRCode(string Content, QRCodeEncoder.ENCODE_MODE QRCodeEncodeMode, QRCodeEncoder.ERROR_CORRECTION QRCodeErrorCorrect, int QRCodeVersion, int QRCodeScale, int size, int border, Color ForegroundColor) {
			QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
			qrCodeEncoder.QRCodeEncodeMode = QRCodeEncodeMode;
			qrCodeEncoder.QRCodeErrorCorrect = QRCodeErrorCorrect;
			qrCodeEncoder.QRCodeScale = QRCodeScale;
			qrCodeEncoder.QRCodeVersion = QRCodeVersion;
			qrCodeEncoder.QRCodeForegroundColor = ForegroundColor;//前景色
			System.Drawing.Image image = qrCodeEncoder.Encode(Content);


			#region 根据设定的目标图片尺寸调整二维码QRCodeScale设置，并添加边框
			if (size > 0) {
				//当设定目标图片尺寸大于生成的尺寸时，逐步增大方格尺寸
				#region 当设定目标图片尺寸大于生成的尺寸时，逐步增大方格尺寸
				while (image.Width < size) {
					qrCodeEncoder.QRCodeScale++;
					System.Drawing.Image imageNew = qrCodeEncoder.Encode(Content);
					if (imageNew.Width < size) {
						image = new System.Drawing.Bitmap(imageNew);
						imageNew.Dispose();
						imageNew = null;
					}
					else {
						qrCodeEncoder.QRCodeScale--; //新尺寸未采用，恢复最终使用的尺寸
						imageNew.Dispose();
						imageNew = null;
						break;
					}
				}
				#endregion

				//当设定目标图片尺寸小于生成的尺寸时，逐步减小方格尺寸
				#region 当设定目标图片尺寸小于生成的尺寸时，逐步减小方格尺寸
				while (image.Width > size && qrCodeEncoder.QRCodeScale > 1) {
					qrCodeEncoder.QRCodeScale--;
					System.Drawing.Image imageNew = qrCodeEncoder.Encode(Content);
					image = new System.Drawing.Bitmap(imageNew);
					imageNew.Dispose();
					imageNew = null;
					if (image.Width < size) {
						break;
					}
				}
				#endregion

				//如果目标尺寸大于生成的图片尺寸，则为图片增加白边
				#region 如果目标尺寸大于生成的图片尺寸，则为图片增加白边
				if (image.Width <= size) {
					//根据参数设置二维码图片白边的最小宽度
					#region 根据参数设置二维码图片白边的最小宽度
					if (border > 0) {
						while (image.Width <= size && size - image.Width < border * 2 && qrCodeEncoder.QRCodeScale > 1) {
							qrCodeEncoder.QRCodeScale--;
							System.Drawing.Image imageNew = qrCodeEncoder.Encode(Content);
							image = new System.Drawing.Bitmap(imageNew);
							imageNew.Dispose();
							imageNew = null;
						}
					}
					#endregion

					//当目标图片尺寸大于二维码尺寸时，将二维码绘制在目标尺寸白色画布的中心位置
					if (image.Width < size) {
						//新建空白绘图
						System.Drawing.Bitmap panel = new System.Drawing.Bitmap(size, size);
						System.Drawing.Graphics graphic0 = System.Drawing.Graphics.FromImage(panel);
						int p_left = 0;
						int p_top = 0;
						if (image.Width <= size) //如果原图比目标形状宽
                        {
							p_left = (size - image.Width) / 2;
						}
						if (image.Height <= size) {
							p_top = (size - image.Height) / 2;
						}

						//将生成的二维码图像粘贴至绘图的中心位置
						graphic0.DrawImage(image, p_left, p_top, image.Width, image.Height);
						image = new System.Drawing.Bitmap(panel);
						panel.Dispose();
						panel = null;
						graphic0.Dispose();
						graphic0 = null;
					}
				}
				#endregion
			}
			#endregion

			return image;
		}





		/// <summary>  
		/// 生成二维码图片  
		/// </summary>  
		/// <param name="codeNumber">要生成二维码的字符串</param>       
		/// <param name="size">大小尺寸</param>  
		/// <returns>二维码图片</returns>  
		public Image Create_ImgCode(string codeNumber, int size, Color ForegroundColor, int imgSize) {
			//创建二维码生成类  
			QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
			//设置编码模式  
			qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
			//设置编码测量度  
			qrCodeEncoder.QRCodeScale = size;
			//设置编码版本  
			qrCodeEncoder.QRCodeVersion = 0;
			//设置编码错误纠正  
			qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.H;
			qrCodeEncoder.QRCodeForegroundColor = ForegroundColor;//前景色
			//生成二维码图片  
			System.Drawing.Bitmap image = qrCodeEncoder.Encode(codeNumber);
			if (imgSize > 0) {
				while (image.Width < imgSize) {
					qrCodeEncoder.QRCodeScale++;
					System.Drawing.Image imageNew = qrCodeEncoder.Encode(codeNumber);
					if (imageNew.Width < imgSize) {
						image = new System.Drawing.Bitmap(imageNew);
						imageNew.Dispose();
						imageNew = null;
					}
					else {
						qrCodeEncoder.QRCodeScale--; //新尺寸未采用，恢复最终使用的尺寸
						imageNew.Dispose();
						imageNew = null;
						break;
					}
				}
				while (image.Width > imgSize && qrCodeEncoder.QRCodeScale > 1) {
					qrCodeEncoder.QRCodeScale--;
					System.Drawing.Image imageNew = qrCodeEncoder.Encode(codeNumber);
					image = new System.Drawing.Bitmap(imageNew);
					imageNew.Dispose();
					imageNew = null;
					if (image.Width < imgSize) {
						break;
					}
				}

			}
			image.SetResolution(600,600);

			return image;
		}






		/// <summary>
		/// 裁剪图片
		/// </summary>
		/// <param name="stream">图片流</param>
		/// <param name="startX">开始坐标X</param>
		/// <param name="startY">开始坐标Y</param>
		/// <param name="getX">截取横向距离</param>
		/// <param name="getY">截取纵向距离</param>
		/// <returns>图片base64编码</returns>
		public Image CutImage(Image img, int startX, int startY, int getX, int getY) {

			int w = img.Width;
			int h = img.Height;

			if (startX < w && startY < h) {
				if (getX + startX > w) {
					getX = w - startX;
				}
				if (startY + getY > h) {
					getY = h - startY;
				}
			}

			Bitmap destBitmap = new Bitmap(getX, getY);//目标图
			Rectangle destRect = new Rectangle(0, 0, getX, getY); //生成图区域
			Rectangle srcRect = new Rectangle(startX, startY, getX, getY);//截取区域
			Graphics g = Graphics.FromImage(destBitmap);
			g.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel);
			g.Dispose();
			g = null;
			destBitmap.SetResolution(600, 600);
			return destBitmap;
		}


		/// <summary>
		/// 图片拼接
		/// </summary>
		/// <param name="sFromFilePath"></param>
		/// <param name="saveFilePath"></param>
		/// <param name="width"></param>
		/// <param name="height"></param>
		/// <param name="spaceX"></param>
		/// <param name="spaceY"></param>
		public Image JoinImage(Image Img1, Image Img2, Image Img3, Image Img4)//实现左右拼接图片  
		{
			int imgHeight = 0, imgWidth = 0;
			imgWidth = Img1.Width + Img2.Width;
			imgHeight = 2 * Math.Max(Img1.Height, Img2.Height);
			Bitmap joinedBitmap = new Bitmap(imgWidth, imgHeight);
			Graphics graph = Graphics.FromImage(joinedBitmap);
			graph.DrawImage(Img1, 0, 0, Img1.Width, Img1.Height);
			graph.DrawImage(Img2, Img1.Width, 0, Img2.Width, Img2.Height);
			graph.DrawImage(Img3, 0, Img1.Height, Img3.Width, Img3.Height);
			graph.DrawImage(Img4, Img3.Width, Img2.Height, Img4.Width, Img4.Height);

			graph.Dispose();
			graph = null;
			joinedBitmap.SetResolution(600, 600);
			return joinedBitmap;
		}


		public Image JoinImage(Image Img1, Image Img2)//实现左右拼接图片  
		{
			int imgHeight = 0, imgWidth = 0;
			imgWidth = Img1.Width + Img2.Width;
			imgHeight = Math.Max(Img1.Height, Img2.Height);
			Bitmap joinedBitmap = new Bitmap(imgWidth, imgHeight);
			Graphics graph = Graphics.FromImage(joinedBitmap);
			graph.DrawImage(Img1, 0, 0, Img1.Width, Img1.Height);
			graph.DrawImage(Img2, Img1.Width, 0, Img2.Width, Img2.Height);
 
			graph.Dispose();
			graph = null;
			return joinedBitmap;
		}



		/// <summary>
		/// 调用此函数后使此两种图片合并，类似相册，有个
		/// 背景图，中间贴自己的目标图片
		/// </summary>
		/// <param name="sourceImg">相框图片</param>
		/// <param name="destImg">照片图片</param>
		public Image CombinImage(Image sourceImg, Image destImg) {
			 
			//从指定的System.Drawing.Image创建新的System.Drawing.Graphics       
			Graphics g = Graphics.FromImage(sourceImg);
			 
			g.DrawImage(destImg, 170, 35, 212, 203);
			 
			GC.Collect();
			 
			return sourceImg;
		}


		/// <summary>
		/// 创建彩色字体图片信息
		/// </summary>
		/// <param name="fontColor">字体颜色</param>
		/// <param name="fontStr">字体字符</param>
		/// x  字体在画布上存在的横坐标
		/// y 字体在画布上存在的纵坐标
		/// <returns></returns>
		public Image ColorFont(List<Brush> fontColor, string fontStr, int cutLength) {
			//字体信息
			//路径             
			string path = @"E:\tds.ttf";
			//读取字体文件             
			PrivateFontCollection pfc = new PrivateFontCollection();
			pfc.AddFontFile(path);
			//实例化字体             
			Font f = new Font(pfc.Families[0], 16);
			Bitmap bm = new Bitmap(161, 79);
			bm.MakeTransparent(Color.White);
			Graphics g = Graphics.FromImage(bm);
			
			int size = 26;
			var s1 = fontStr.Substring(0, cutLength);
			var s2 = fontStr.Substring(cutLength, cutLength);
			var s3 = fontStr.Substring(2 * cutLength, cutLength);
			var s4 = fontStr.Substring(3 * cutLength, cutLength);
			
			var b1 = fontColor[0];
			var b2 = fontColor[1];
			var b3 = fontColor[2];
			var b4 = fontColor[3];
			using (var p = new GraphicsPath()) {
				p.AddString(s1.ToString(), f.FontFamily,0, size, new Point(2, 2),StringFormat.GenericDefault);
				g.FillPath(b1, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s2.ToString(), f.FontFamily, 0, size, new Point(size + 50, 2), StringFormat.GenericDefault);
				g.FillPath(b2, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s3.ToString() + "   ", f.FontFamily, 0, size, new Point(2, 10 + size), StringFormat.GenericDefault);
				g.FillPath(b3, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s4.ToString(), f.FontFamily, 0, size, new Point(size + 50, size + 10), StringFormat.GenericDefault);
				g.FillPath(b4, p);
			}
			bm.SetResolution(600, 600);
			g.Dispose();
			return bm;

		}

		/// <summary>
		/// 创建彩色字体图片信息
		/// </summary>
		/// <param name="fontColor">字体颜色</param>
		/// <param name="fontStr">字体字符</param>
		/// x  字体在画布上存在的横坐标
		/// y 字体在画布上存在的纵坐标
		/// <returns></returns>
		public Image ColorFontWeb(List<Brush> fontColor, string fontStr, int cutLength) {
			//字体信息
			//路径             
			string path = @"E:\tds.ttf";
			//读取字体文件             
			PrivateFontCollection pfc = new PrivateFontCollection();
			pfc.AddFontFile(path);
			//实例化字体             
			Font f = new Font(pfc.Families[0], 16);

			Image img = Image.FromFile("E:\\FontUpload\\图片2.jpg");

			Graphics g = Graphics.FromImage(img);

			int size = 26;
			var s1 = fontStr.Substring(0, cutLength);
			var s2 = fontStr.Substring(cutLength, cutLength);
			var s3 = fontStr.Substring(2 * cutLength, cutLength);
			var s4 = fontStr.Substring(3 * cutLength, cutLength);

			var b1 = fontColor[0];
			var b2 = fontColor[1];
			var b3 = fontColor[2];
			var b4 = fontColor[3];
			using (var p = new GraphicsPath()) {
				p.AddString(s1.ToString(), f.FontFamily, 0, size, new Point(2, 200), StringFormat.GenericDefault);
				g.FillPath(b1, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s2.ToString(), f.FontFamily, 0, size, new Point(size + 50, 200), StringFormat.GenericDefault);
				g.FillPath(b2, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s3.ToString() + "   ", f.FontFamily, 0, size, new Point(2, 210 + size), StringFormat.GenericDefault);
				g.FillPath(b3, p);
			}
			using (var p = new GraphicsPath()) {
				p.AddString(s4.ToString(), f.FontFamily, 0, size, new Point(size + 50, size + 210), StringFormat.GenericDefault);
				g.FillPath(b4, p);
			}
			 
			g.Dispose();
			return img;

		}

		/// <summary>
		/// 获取高清的Graphics
		/// </summary>
		/// <param name="img"></param>
		/// <returns></returns>
		public Graphics GetGraphics(Image img) {
			var g = Graphics.FromImage(img);
			//设置质量
			g.SmoothingMode = SmoothingMode.HighQuality;
			g.CompositingQuality = CompositingQuality.HighQuality;
			//InterpolationMode不能使用High或者HighQualityBicubic,如果是灰色或者部分浅色的图像是会在边缘处出一白色透明的线
			//用HighQualityBilinear却会使图片比其他两种模式模糊（需要肉眼仔细对比才可以看出）
			g.InterpolationMode = InterpolationMode.Default;
			g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
			return g;
		}



		/// <summary>
		/// 将Image实例保存到文件,注意此方法不执行 img.Dispose()
		/// 图片保存时本可以直接使用destImage.Save(path, ImageFormat.Jpeg)，但是这种方法无法进行进一步控制图片质量
		/// </summary>
		/// <param name="path"></param>
		/// <param name="img"></param>
		/// <param name="quality">1~100整数,无效值，则取默认值95</param>
		/// <param name="mimeType"></param>
		public void SaveImage2File(string path, Image destImage, int quality, string mimeType = "image/png") {
			if (quality <= 0 || quality > 100) quality = 95;
			//创建保存的文件夹
			FileInfo fileInfo = new FileInfo(path);
			if (!Directory.Exists(fileInfo.DirectoryName)) {
				Directory.CreateDirectory(fileInfo.DirectoryName);
			}
			//设置保存参数，保存参数里进一步控制质量
			EncoderParameters encoderParams = new EncoderParameters();
			long[] qua = new long[] { quality };
			EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
			encoderParams.Param[0] = encoderParam;
			//获取指定mimeType的mimeType的ImageCodecInfo
			var codecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(ici => ici.MimeType == mimeType);
			destImage.Save(path, codecInfo, encoderParams);
		}

	}
}
